package protocol

import (
	"context"
	"fmt"
	"net/http"
	"os"
	"pd/conf"
	"pd/modle"
	"pd/modules"

	// ar_api "pd/modules/allowed_requrl/api"
	// ar_impl "pd/modules/allowed_requrl/impl"
	// as_api "pd/modules/allowed_sign/api"
	// as_impl "pd/modules/allowed_sign/impl"
	// "pd/modules/rdp_white_ip/api"
	// "pd/modules/rdp_white_ip/impl"
	_ "pd/modules/all"
	"time"

	"github.com/gin-gonic/gin"
	log "github.com/marmotedu/iam/pkg/log"
)

type HttpService struct {
	// 指定router
	r gin.IRouter
	// 这个server对象才是最终的服务的实例,会把这个server端,来负责启动或者停止,完成下面两个核心方法
	server *http.Server
	l      log.Logger
}

func NewHttpService() *HttpService {
	// new 了一个gin router实例，并没有加载handler
	r := gin.Default()
	server := &http.Server{
		// 客户端先读到header再读到body，比如option请求只有header没有body
		// 去探测服务端支不支持get,post等方法
		ReadHeaderTimeout: 60 * time.Second,
		// HTTP连接建立过后，server端在读取用户请求的时候，读header，body，命令行
		ReadTimeout: 60 * time.Second,
		// 服务端发送响应的时间
		WriteTimeout: 60 * time.Second,
		//
		IdleTimeout: 60 * time.Second,
		// header的报文最大容量
		MaxHeaderBytes: 1 << 20, //1M
		// 监听地址
		Addr:    conf.C().App.HttpAddr(),
		Handler: r,
	}
	return &HttpService{
		server: server,
		l:      log.WithName("HttpService"),
		r:      r,
	}
}

// func (s *HttpService) RegistryAll() {
// 	go func() {
// 		as := as_impl.NewAsImpl()
// 		ash := as_api.NewAsHttpHandler(as)
// 		ash.GinRegistry(s.r)
// 	}()

// 	go func() {
// 		ar := ar_impl.NewArImpl()
// 		arh := ar_api.NewArHttpHandler(ar)
// 		arh.GinRegistry(s.r)
// 	}()

// 	go func() {
// 		rwi := impl.NewRwiImpl()
// 		rwih := api.NewRwiHttpHandler(rwi)
// 		rwih.GinRegistry(s.r)
// 	}()

// 	go func() {
// 		di := modle.NewDeviceInfos()
// 		di.Registry(s.r)
// 	}()
// }

// 启动http服务
func (s *HttpService) Start() error {
	// s.RegistryAll()
	modules.InitImpls()
	modules.InitGins(s.r)
	di := modle.NewDeviceInfos()
	di.Registry(s.r)

	//查询已经加载完成的Gin App有哪些
	apps := modules.LoadGinApps()
	s.l.Infof("loaded gin apps :%v", apps)

	// 该操作是阻塞的，监听端口，等待请求
	if err := s.server.ListenAndServe(); err != nil {
		// 如果服务的正常关闭，比如调了stop方法。或者网络正常进行关闭
		// 这种情况下，不能视为异常，无需输出错误日志
		if err == http.ErrServerClosed {
			s.l.Info("service stoped success")
			return nil
		}
		return fmt.Errorf("start service error ,%s", err)
	}

	// 启动HTTP的服务,用HTTP服务启动,是为了兼容其他框架,
	// 若是选gin,则只能用gin了

	return nil
}

// 处理外部的中断信号，比如Terminal
func (s *HttpService) WaitStop(ch <-chan os.Signal) error {
	// 关闭之前先将log全部输出
	defer log.Flush()
	for v := range ch {
		switch v {
		// case syscall.SIGTERM:
		default:
			s.l.Debugf("received signal :%s", v)
			err := s.Stop()
			if err != nil {
				return err
			}
		}
	}
	return nil
}

// 优雅关闭
func (s *HttpService) Stop() error {
	s.l.Debug("start graceful shutdown")
	// 为shutdown构建一个ctx
	ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
	defer cancel()
	// 优雅关闭HTTP服务，新的请求不再接收，旧的请求会正常响应
	if err := s.server.Shutdown(ctx); err != nil {
		s.l.Errorf("shut down http service error,%s", err)
	}

	return nil
}
